#include "render/Shader.h"
#include <vector>
#include <fstream>

static std::string readFile(const std::string& p){ std::ifstream f(p, std::ios::binary); if(!f) return {}; std::vector<char> b((std::istreambuf_iterator<char>(f)), std::istreambuf_iterator<char>()); return std::string(b.begin(), b.end()); }

bool Shader::loadFromFiles(const std::string& vertPath, const std::string& fragPath) {
    std::string vs = readFile(vertPath);
    std::string fs = readFile(fragPath);
    if (vs.empty() || fs.empty()) return false;
    GLuint v = glCreateShader(GL_VERTEX_SHADER);
    const char* vsrc = vs.c_str();
    glShaderSource(v,1,&vsrc,nullptr);
    glCompileShader(v);
    GLuint f = glCreateShader(GL_FRAGMENT_SHADER);
    const char* fsrc = fs.c_str();
    glShaderSource(f,1,&fsrc,nullptr);
    glCompileShader(f);
    program = glCreateProgram();
    glAttachShader(program,v);
    glAttachShader(program,f);
    glLinkProgram(program);
    glDeleteShader(v);
    glDeleteShader(f);
    return true;
}

void Shader::use() const { glUseProgram(program); }
GLint Shader::uniform(const char* name) const { return glGetUniformLocation(program,name); }
void Shader::setMat4(const char* name, const float* value) const { glUniformMatrix4fv(uniform(name),1,GL_FALSE,value); }
void Shader::setVec3(const char* name, float x, float y, float z) const { glUniform3f(uniform(name),x,y,z); }
void Shader::setFloat(const char* name, float v) const { glUniform1f(uniform(name),v); }